package com.cskaoyan.wordmemorize.service.impl;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cskaoyan.wordmemorize.service.UserPrivilegeService_WF;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
//import com.cskaoyan.wordmemorize.common.business.IdBatchDeleter;
import com.cskaoyan.wordmemorize.common.constant.CommonConstant;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.TopicConverter;
import com.cskaoyan.wordmemorize.converter.UserPrivilegeConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.*;
import com.cskaoyan.wordmemorize.dto.app.*;
import com.cskaoyan.wordmemorize.request.*;
import com.cskaoyan.wordmemorize.service.UserPrivilegeService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.prompt.ChatPromptTemplate;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserPrivilegeServiceImpl_WF implements UserPrivilegeService_WF {

    @Resource
    UserPrivilegeConverter converter;

    @Resource
    UserFavoriteMapper userFavoriteMapper;

    @Resource
    UserVocRevMapper userVocRevMapper;

    @Resource
    LevelPrivilegeMapper levelPrivilegeMapper;

    @Resource
    UserNotRememberMapper userNotRememberMapper;

    @Resource
    UserVocExampleSentenceMapper userVocExampleSentenceMapper;

    @Resource
    UserCheckinStatisticsMapper userCheckinStatisticsMapper;


    @Resource
    UserCheckinMapper userCheckinMapper;


    @Resource
    ReviewSubTopicMapper reviewSubTopicMapper;

    @Resource
    ReviewTopicOptionMapper reviewTopicOptionMapper;

    @Resource
    TopicConverter topicConverter;

    @Resource
    ReviewTopicMapper reviewTopicMapper;

    @Resource
    UserVocAISituationMapper userVocAISituationMapper;

    @Resource
    UserPrivilegeHistoryMapper userPrivilegeHistoryMapper;

    @Resource
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;

    @Resource
    UserMapper userMapper;

    @Resource
    UserVocBoundLogMapper userVocBoundLogMapper;

    @Resource
    LevelMapper levelMapper;


    @Resource
    VocMapper vocMapper;


    @Resource
    UserPrivilegeServiceImpl_WF own;

    @Resource
    VocBookMapper vocBookMapper;


    private ChatClient chatClient;

    public UserPrivilegeServiceImpl_WF(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }


    @Override
    public UserVocBookStatisticsDTO getSelectedBookStatistics(Long userId, Long bookId) {
        return null;
    }


    @Override
    @Transactional
    public void addFavoriteBulk(List<UserFavoriteCommand> userFavoriteCommands, Long userId) {

    }


    @Override
    public void addFavorite(UserFavoriteCommand userFavoriteCommand, Long userId) {

    }

    @Override
    @Transactional
    public void cancelFavorite(List<Long> ids, Long userId) {

         }

    @Override
    public PageDTO<UserFavoriteDTO> getUserFavoriteList(PageRequest pageRequest, Long userId) {

        return null;
    }



    @Override
    public void addUserVocSentence(UserVocExampleSentenceCommand command, Long userId) {

    }

    @Override
    public PageDTO<DisplayUserVocSentenceDTO> getUserVocSentence(PageRequest pageRequest, Long userId) {

        return null;
    }

    @Override
    public void updateUserVocSentence(UserVocExampleSentenceCommand command, Long userId) {
    }

    @Override
    public void deleteUserVocSentence(Long id) {

    }

    @Override
    @Transactional
    public void notRemember(Long vocId, Long userId) {

    }

    /*
          取消标识不背的话
     */
    @Override
    public void cancelNotRemember(Long vocId, Long userId) {
    }



    @Override
    public List<UserVocAISituationDTO> getAIReviewReadOptions() {
        List<UserVocAISituationDO> aiReadSituationInfo
                = userVocAISituationMapper.getAIReadSituationInfo();

        return converter.userVocAISituationDOs2DTOs(aiReadSituationInfo);
    }

    @Override
    public Integer getUserVocAIReadRemainFreeCount(Long userId) {

        // 查询特权信息，查询免费使用次数
        LambdaQueryWrapper<LevelPrivilegeDO> levelPrivilegeWrapper = new LambdaQueryWrapper<>();
        levelPrivilegeWrapper.eq(LevelPrivilegeDO::getPrivilegeCode, CommonConstant.USER_PRIVILEGE_CODE_AI_READ);
        LevelPrivilegeDO levelPrivilegeDO = levelPrivilegeMapper.selectOne(levelPrivilegeWrapper);

        // 查询使用历史数据
        LambdaQueryWrapper<UserPrivilegeUseStatisticsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPrivilegeUseStatisticsDO::getUserId, userId)
                .eq(UserPrivilegeUseStatisticsDO::getPrivilegeCode, CommonConstant.USER_PRIVILEGE_CODE_AI_READ);

        UserPrivilegeUseStatisticsDO userPrivilegeUseStatisticsDO = userPrivilegeHistoryMapper.selectOne(queryWrapper);
        if (userPrivilegeUseStatisticsDO == null) {
            // 说明是第一次使用
            UserPrivilegeUseStatisticsDO toInsert = new UserPrivilegeUseStatisticsDO();
            toInsert.setUserId(userId);
            toInsert.setPrivilegeCode(CommonConstant.USER_PRIVILEGE_CODE_AI_READ);
            toInsert.setUseCount(0);
            userPrivilegeHistoryMapper.insert(toInsert);
            // 直接返回免费使用次数
            return levelPrivilegeDO.getFreeCount();
        }
        int remains = levelPrivilegeDO.getFreeCount() - userPrivilegeUseStatisticsDO.getUseCount();
        if (remains > 0) {
            return remains;
        }
        return 0;
    }

    @Value("classpath:/prompt/ai-read-system-message.st")
    private org.springframework.core.io.Resource systemResource;

    @Value("classpath:/prompt/ai-read-user-message.st")
    private org.springframework.core.io.Resource userResource;

    @Override
    public List<AIReviewReadDTO> getAIReviewReadContent(AIReviewReadCommand command, Long userId) {
        // 扣减单词上限
        LambdaQueryWrapper<UserVocBoundStatisticsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserVocBoundStatisticsDO::getUserId, userId);
        UserVocBoundStatisticsDO userVocBoundStatisticsDO
                = userVocBoundStatisticsMapper.selectOne(queryWrapper);

        LambdaQueryWrapper<LevelPrivilegeDO> levelPrivilegeWrapper = new LambdaQueryWrapper<>();
        levelPrivilegeWrapper.eq(LevelPrivilegeDO::getPrivilegeCode, CommonConstant.USER_PRIVILEGE_CODE_AI_READ);
        LevelPrivilegeDO levelPrivilegeDO = levelPrivilegeMapper.selectOne(levelPrivilegeWrapper);
        if (userVocBoundStatisticsDO.getAvailable() < levelPrivilegeDO.getRequireVocBound()) {
            throw new BusinessException(ResultCodeEnum.USER_VOC_BOUND_NOT_ENOUGH);
        }


        // 构造系统提示词
        PromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);

        // 构造用户提示词
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("situation", command.getSituationName());
        paramMap.put("option", command.getOptionName());
        paramMap.put("words", command.getVocList().toString());
        if ("教育模式".equals(command.getSituationName())) {
            paramMap.put("type", "短文");
        } else if ("对话模式".equals(command.getSituationName())) {
            paramMap.put("type", "对话");
        } else {
            paramMap.put("type", "故事");
        }
        PromptTemplate userPrompt = new PromptTemplate(userResource, paramMap);

        ChatPromptTemplate chatPromptTemplate = new ChatPromptTemplate(Arrays.asList(systemPromptTemplate, userPrompt));

        List<AIReviewReadDTO> result = chatClient.prompt(chatPromptTemplate.create())
                .call()
                .entity(new ParameterizedTypeReference<List<AIReviewReadDTO>>() {
                });

        own.afterGenerateAIRead(userId, levelPrivilegeDO);
        return result;
    }

    @Transactional
    public void afterGenerateAIRead(Long userId, LevelPrivilegeDO levelPrivilegeDO) {
        // 扣减单词上限
        LambdaUpdateWrapper<UserVocBoundStatisticsDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(UserVocBoundStatisticsDO::getUserId, userId)
                .setSql("available = available - " + levelPrivilegeDO.getRequireVocBound());
        userVocBoundStatisticsMapper.update(updateWrapper);

        // 添加单词上限使用记录
        UserVocBoundLogDO userVocBoundLogDO = new UserVocBoundLogDO();
        userVocBoundLogDO.setUserId(userId);
        userVocBoundLogDO.setType(CommonConstant.USER_VOC_BOUND_CHANGE_TYPE_EXCHANGE);
        userVocBoundLogDO.setCount(levelPrivilegeDO.getRequireVocBound());
        userVocBoundLogDO.setDescription(CommonConstant.USER_VOC_BOUND_DESCRIPTION_AI_READ);
        userVocBoundLogDO.setLogDate(LocalDate.now());
        userVocBoundLogMapper.insert(userVocBoundLogDO);

        // 修改数据库中的使用次数
        LambdaUpdateWrapper<UserPrivilegeUseStatisticsDO> privelegeUseHistoryWrapper = new LambdaUpdateWrapper<>();
        privelegeUseHistoryWrapper.eq(UserPrivilegeUseStatisticsDO::getUserId, userId)
                .eq(UserPrivilegeUseStatisticsDO::getPrivilegeCode, CommonConstant.USER_PRIVILEGE_CODE_AI_READ)
                .setSql("use_count = use_count + 1");
        userPrivilegeHistoryMapper.update(privelegeUseHistoryWrapper);
    }

    @Override
    public boolean saveBatch(Collection<UserFavoriteDO> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdateBatch(Collection<UserFavoriteDO> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean updateBatchById(Collection<UserFavoriteDO> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdate(UserFavoriteDO entity) {
        return false;
    }

    @Override
    public UserFavoriteDO getOne(Wrapper<UserFavoriteDO> queryWrapper, boolean throwEx) {
        return null;
    }

    @Override
    public Optional<UserFavoriteDO> getOneOpt(Wrapper<UserFavoriteDO> queryWrapper, boolean throwEx) {
        return Optional.empty();
    }

    @Override
    public Map<String, Object> getMap(Wrapper<UserFavoriteDO> queryWrapper) {
        return null;
    }

    @Override
    public <V> V getObj(Wrapper<UserFavoriteDO> queryWrapper, Function<? super Object, V> mapper) {
        return null;
    }

    @Override
    public BaseMapper<UserFavoriteDO> getBaseMapper() {
        return null;
    }

    @Override
    public Class<UserFavoriteDO> getEntityClass() {
        return null;
    }
}
